const rewire = require('rewire')
const R = require('ramda')
const utils = rewire('../common/utils.cjs')

function deleteRedundantSql(table, field) {
  const sql = `
              delete from ${table} where id in (
                      select id from (
                              select id from ${table} where ${field} in (
                                      select ${field} from ${table} GROUP BY ${field} HAVING count(1)>1
                              ) and id not in (select max(id) from ${table} GROUP BY ${field} HAVING count(1)>1)
                      ) as tmp
              )
              `
  return sql
}

async function notInTable(db, table, field, data) {
  if (R.length(data) == 0) {
    return []
  }
  if (R.length(data) > 3000) {
    const pies = utils.splitArray(data, 2)
    const result = await Promise.all(pies.map(R.partial(notInTable, [db, table, field])))
    return [].concat(...result)
  }
  else {
    const dbdata = await db
          .select(field)
          .from(table).where(field, data, 'in')
          .queryList()
    const readIds = dbdata.map(item => item[field])
    return utils.arraySub(data, readIds)
  }
}

async function saveOrUpdatePrimary(db, table, primaryKey, key, item) {
  const info = await db
        .select("*")
        .from(table)
        .where(key, item[key])
        .queryRow()
  if (info) {
    item[primaryKey] = info[primaryKey]
    await db
      .update(table, item)
      .where(primaryKey, info[primaryKey])
      .execute()
  }
  else {
    await db.insert(table, item).execute()
  }
}

async function insertAll(db, table, data) {
  if (R.isEmpty(data)) {
    return
  }
  if (R.length(data) > 1000) {
    const pies = utils.splitArray(data, 2)
    await Promise.all(pies.map(R.partial(insertAll, [db, table])))
  }
  else {
    await db.insert(table, data).execute()
  }
}

async function insertAllNotIn(db, table, field, data) {
  const notInFields = await notInTable(db, table, field, R.map(function(item) { return item[field]}, data))
  const fdata = R.filter(function(item) {
    return notInFields.includes(item[field])
  }, data)
  await insertAll(db, table, fdata)
}

module.exports = {deleteRedundantSql, insertAll, notInTable, insertAllNotIn, saveOrUpdatePrimary}
